package it.ap.sa.core.audit.config;

import java.util.ArrayList;
import java.util.List;

import org.audit4j.core.AuditManager;
import org.audit4j.core.Context;
import org.audit4j.core.RunStatus;
import org.audit4j.core.dto.AuditEvent;
import org.audit4j.core.dto.Field;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import it.ap.sa.core.utils.AuthUtils;
import it.ap.sa.core.utils.SpringContextProvider;
import it.ap.sa.core.utils.costants.MdcConstants;

/**
 * Audit4JWriter scrive i log prodotti a seguito della navigazione dell'utente usando audit4j. 
 * (Scrittuta su DB)
 * 
 * @author russo
 */
public class Audit4JWriter implements IAuditWriter {

	private static final Logger logger = LoggerFactory.getLogger(Audit4JWriter.class.getName());

	private AuditConfig auditconfig = SpringContextProvider.getApplicationContext().getBean(AuditConfig.class);

	/**
	 * Metodo per inserire in audit una revisione, per default ai parametri eventualmente forniti in ingresso
	 * aggiungo l'username dell'utente autenticato.
	 * 
	 * @param {@link String} action, operazione eseguita
	 * @param {@link List<Field>} fields, lista parametri
	 */
	@Override
	public void writeEvent(String action, List<Field> fields) {
		try {
			/**
			 * controllo se audit4j è in esecuzione
			 */
			if( Context.getStatus().equals(RunStatus.RUNNING) ) {

				AuditManager manager = AuditManager.getInstance();

				if (fields == null) fields = new ArrayList<Field>();

				fields.add(new Field(MdcConstants.USER_USERNAME.value(), AuthUtils.getLoggedUsername()));
				//
				AuditEvent audit = new AuditEvent();
					audit.setAction(action);
					audit.setFields(fields);
				manager.audit(audit);
			}else
			  logger.error("Impossibile loggare con Audit4j >>> IS NOT RUNNING");
			
		} catch (Exception e) {
			logger.error("Audit4JWriter.writeEvent " + e, e);
		}
	}

	/**
	 * Metodo per l'avvio programmatico di audit4j. 
	 * Prima di startare il servizio controllo che non sia già in esecuzione, se cosi non fosse devo prima stopparlo.
	 */
	@Override
	public void initialize() {
		try {
			logger.info(">>>>>>>>>>>>>>>>>>>>>>> Inizilizzazione di Audit4j ... IN CORSO <<<<<<<<<<<<<<<<< ");

			if(!Context.getStatus().equals(RunStatus.READY) && !Context.getStatus().equals(RunStatus.STOPPED)) {
				logger.warn("Servizio gia' attivo. Stopping Audit4j ... ");
				
				auditconfig.shutdown();
			}
			/**
		     * This allows to create one time configuration setting to Audit4j.
		     */
			auditconfig.startWithConfiguration();
			
			logger.info(">>>>>>>>>>>>>>>>>>>>>>> Inizilizzazione di Audit4j ... TERMINATA <<<<<<<<<<<<<<<<< ");
		}catch(Exception e){
			logger.error("Error start audit4j service ... continue anyway " + e, e);
		}
	}

	/**
	 * Metodo per lo stop programmatico di audit4j. 
	 */
	@Override
	public void stopWriter() {
		try {
			logger.info(">>>>>>>>>>>>>>>>>>>>>>> Stop service di Audit4j ... IN CORSO <<<<<<<<<<<<<<<<< ");
			
			auditconfig.shutdown();
			
			logger.info(">>>>>>>>>>>>>>>>>>>>>>> Stop service di Audit4j ... TERMINATO <<<<<<<<<<<<<<<<< ");
		} catch (Exception ex) {
			logger.error("Error shutdown audit4j service ... continue anyway", ex);
		}
	}
}
